home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 076-100 / disk_096 / popupmenu / popdoc < prev    next >
Text File  |  1992-05-06  |  17KB  |  370 lines

  1. POP-UP MENU MODULE DOCUMENTATION
  2.  
  3. Introduction
  4.  
  5. It has been perceived by some that Intuition's requirement that menus be
  6. attached to the very top of screens is a flaw.  Many windowing systems
  7. provide "pop-up" menus which can appear anywhere on the screen, typically
  8. for context-specific input of a multiple-choice selection.  In the
  9. interests of experimenting with the Amiga's user interface (in this case
  10. extending it to include pop-up menus), the code bundled with this document
  11. is placed in the public domain for use, alteration, discussion, and
  12. enhancement.  I hope someone somewhere finds it useful.
  13.  
  14. Derek Zahn  (my Amiga hat -- Gambit Software, Madison WI)
  15. USENET:         ...!{allegra,heurikon,ihnp4,seismo,ucbvax}!uwvax!derek
  16.  
  17. Files
  18.  
  19. makefile: constructs the demonstration program 'demo' with 'make'.
  20.   The command 'make pop.o' will just make the pop-up menu object module
  21. pop.c: source file for the pop-up menu module
  22. popmenu.h: include file containing essential constant definitions;
  23.   should be included by any program using pop-up menus
  24. demo.c: example program making use of the pop-up menu module
  25.  
  26. 1. Features
  27.  
  28. This small chunk of code provides pop-up menu functionality that utilizes
  29. data structures compatible with the existing methods for specifying
  30. conventional Intuition menus.  As will be described in sections 3 and 4 of
  31. this document, some flag values have been added to provide control
  32. useful for pop-up menus, some flag values are not meaningful here, some
  33. are unsupported, and some fields of the Menu structure are used in ways
  34. different from Intuition's.  A potential user of the code should read and
  35. understand this document and examine the simple sample cases provided in
  36. the demonstration program.
  37.  
  38. The interface, as will be seen in section 2, is a very simple blocking
  39. function call that will retrieve a pop-up menu selection from the specified
  40. menu.  This interface differs considerably from the normal Intuition menu
  41. interface which sends messages to the user's IDCMP message port.  The reason
  42. for this difference is as follows:  The standard Intuition menu strip
  43. associated with a particular window is available for use any time the
  44. window is active (unless specifically shut off).  The physical mechanism 
  45. allowing the user to communicate her desire to make a menu choice, and then 
  46. to do so, is built into Intuition at a fundamental level.  This is not the 
  47. case for an application-level pop-up menu facility.  There is no clear 
  48. universally acceptable method for removing from the application program the 
  49. responsibility for recognizing the need to invoke the pop-up menu function.
  50.  
  51. I had considered writing another level of interface to this code that would
  52. spawn off a Task which would be responsible for rendering and handling the
  53. pop-up menus in response to recognized human interaction, and then notify
  54. the program via the IDCMP port with a new set of IntuiMessage Classes (such
  55. as POPMENUVERIFY, POPMENUHIT, etc).  However, I became bogged down in trying
  56. to devise a good scheme for registering pop-up menus and then detecting an 
  57. appropriate time to bring up them up.  I would welcome discussion on this
  58. point.
  59.  
  60. Despite the lack of procedural alignment with Intuition menus (these pop-up 
  61. menus are much more like AutoRequests), clearly there are instances where the
  62. interface is reasonably natural anyway.  For instance, pop-up menus might be
  63. very handy for providing a quick way, in a word processing program, to change
  64. the font of a selected bunch of text -- using a pop-up menu saves the mouse
  65. movement required to make an Intuition menu selection, allows conservation
  66. of space that would be taken up by window gadgets to perform similar
  67. operations, and requires less memorization than keyboard-command equivalents
  68. (although Power Users may very well migrate there as they become familiar
  69. with the program).
  70.  
  71. These pop-up menus are constructed with standard Intuition Menu and MenuItem
  72. structures.  Most of the features provided by Intuition menus are supported
  73. in nearly identical fashion, as is described in sections 3 and 4.
  74.  
  75. There are several notable exceptions, however; I do feel that this code is
  76. incomplete.  The facility for providing sub-items is not supported, nor
  77. are multiple menus in a single pop-up menu.  There is also no scheme for
  78. supporting extended selection.  See the Appendix for a discussion of these 
  79. lacks and other qualms I have about the code in its current form.
  80.  
  81. 2. PopChoose
  82.  
  83. The user interface:
  84.  
  85. #include <intuition/intuition.h>
  86. #include "popmenu.h"
  87.  
  88. LONG
  89. PopChoose(menu, win)
  90. struct Menu *menu;
  91. struct Window *win;
  92.  
  93. The argument 'win' specifies the window that is to act as the "parent"
  94. of the the pop-up menu to be rendered.  If this value is NULL, the currently
  95. active window is used.  The argument 'menu' is a specification for the 
  96. pop-up menu, as described in sections 3 and 4 below.
  97.  
  98. If an error is detected or no valid selection is made by the user, -1 is
  99. returned.  If a selection is made, a non-negative value corresponding to
  100. the choice is returned, and is computed as follows:  The first MenuItem
  101. in the Menu is numbered zero; thereafter, each is numbered one higher than
  102. the last as the list of MenuItems is traversed.  This is the same scheme
  103. Intuition uses for the Code field of the class MENUHIT IntuiMessages.
  104.  
  105. PopChoose() creates a new window in which it renders the menu.  It is up to
  106. the caller to be sure that nobody is scribbling indiscriminately on the
  107. screen where the menu is to go.
  108.  
  109. IMPORTANT POINT:  In order to link the pop.o module into an application
  110. program, somewhere in that application the following global variables
  111. MUST be declared:
  112.  
  113. struct IntuitionBase *IntuitionBase;
  114. struct GfxBase *GfxBase;
  115.  
  116. Then, before PopChoose is called, IntuitionBase MUST be set to the result of
  117. successfully opening the intuition.library, and GfxBase MUST be set to the
  118. result of successfully opening the graphics.library.  The potential for
  119. disaster if these steps are not properly taken is great indeed.
  120.  
  121. If you do not understand exactly what is required, examine the code in the
  122. supplied demonstration program, 'demo.c'.
  123.  
  124. 3. The Menu structure
  125.  
  126. This section describes how the fields of the Menu structure are interpreted
  127. by PopChoose().  Some of the fields are interpreted differently than they
  128. are by Intuition; understand the differences before using the code.
  129.  
  130. LeftEdge, TopEdge
  131.  
  132.   These fields contain the upper left corner values for the menu.  Their
  133.   meaning (and perhaps even value) is modified by the Flags POPPOINTREL, 
  134.   POPWINREL, POPTIDY, and POPREMEMBER, as described below.
  135.  
  136. Width, Height
  137.  
  138.   The use of these fields differs considerably from Intuition.  Here, they
  139.   give the TOTAL size of the menu -- all of the MenuItems (and the title,
  140.   if present) must fit inside the rectangle defined by these variables.
  141.  
  142. MenuNext
  143.  
  144.   This field is ignored.
  145.  
  146. MenuName
  147.  
  148.   Use of this field is confusing, as it affects the positioning of the
  149.   MenuItems in the menu.  If this field is NULL, there is no title present
  150.   and the offsets in the MenuItem structures represent true offsets from
  151.   the UL corner of the menu.  If the field is non-null, it is assumed to
  152.   point to a null-terminated character string which will be rendered in the
  153.   top of the menu as the title.  In this case, POPTITLEHEIGHT (defined in
  154.   "popmenu.h") will be silently added to the the TopEdge of each of the 
  155.   MenuItems to take the title into account. This confusing behavior is the 
  156.   result of providing optional menu titles and still retaining compatibility
  157.   with Intuition's notions about what the TopEdge field in a MenuItem means.
  158.  
  159. FirstItem
  160.  
  161.   As with Intuition, this points to the list of MenuItem structures that make
  162.   up the choices in the menu.  This list may be empty.
  163.  
  164. Flags
  165.  
  166.   Flags for Menus mentioned in the Intuition Reference Manual:
  167.  
  168.   MENUENABLED
  169.     If this flag is not set in the menu passed to PopChoose(), -1 will be
  170.     returned immediately.
  171.   
  172.   MIDRAWN
  173.     This flag is unused.
  174.  
  175.   Menu flags (defined in "popmenu.h") added for use by the pop-up menus:
  176.  
  177.   By default, the values in LeftEdge and TopEdge are absolute offsets from
  178.   the upper left corner of the screen.  The following flags alter this.
  179.  
  180.   POPPOINTREL
  181.     This flag, if set, specifies that the LeftEdge and TopEdge fields are
  182.     to represent offsets from the pointer position when PopChoose() was
  183.     called.
  184.  
  185.   POPWINREL
  186.     This flag, if set, specifies that the LeftEdge and TopEdge fields
  187.     represent offsets from the upper left corner of the "parent"
  188.     window. The POPPOINTREL flag takes priority over POPWINREL if both 
  189.     are set.
  190.  
  191.   POPREMEMBER
  192.     This flag, if set, takes effect if the menu passed to PopChoose() has
  193.     previously been used to make a successful selection.  Once this has
  194.     happened and if the POPREMEMBER flag is set, the TopEdge and LeftEdge
  195.     fields will be altered so that on the next call, the menu will appear
  196.     relative to the pointer in such a manner that the last-selected item
  197.     will be pre-selected.
  198.  
  199.   POPTIDY
  200.     This flag, if set, makes sure that the whole menu appears on the screen
  201.     by adjusting its location if part of it would not appear on the screen.
  202.     It should be noted that this process can frustrate the intentions of
  203.     the POPPOINTREL, POPWINREL, and POPREMEMBER flags by making the menu
  204.     appear in an "unexpected" place; however, it does assure that the
  205.     menu will be rendered and that all its items are on-screen.
  206.   
  207.   POPUSED
  208.     This flag is for internal use by PopChoose() -- it indicates
  209.     whether the next call to PopChoose() should treat the POPREMEMBER
  210.     flag as being in effect.
  211.  
  212.   These next flags determine the conditions under which a menu selection is
  213.   considered made.  Note that it is ABSOLUTELY REQUIRED that at least one
  214.   of { POPLEFTBUTTON, POPRIGHTBUTTON } be set AND at least one of
  215.   { POPTRIGGERUP, POPTRIGGERDOWN } be set -- if these conditions are not met,
  216.   the call to PopChoose() will never return!
  217.  
  218.   POPLEFTBUTTON
  219.     Treat the left mouse button as "important" in determining when the user
  220.     is through with the menu.  Both this and POPRIGHTBUTTON may be set, in
  221.     which case, both buttons are important.
  222.  
  223.   POPRIGHTBUTTON
  224.     Treat the right mouse button as "important" in determining when the user
  225.     is through with the menu.
  226.  
  227.   POPTRIGGERUP
  228.     Send the menu away, making a selection if the pointer is over an item,
  229.     and not if not, when the "important" button or buttons is/are released.
  230.     Both this and POPTRIGGERDOWN may be set, in which case both are in
  231.     effect.
  232.  
  233.   POPTRIGGERDOWN
  234.     Send the menu away, making a selection if the pointer is over an item,
  235.     and not if not, when the "important" button or buttons is/are depressed.
  236.  
  237. 4. The MenuItem structure
  238.  
  239. This section describes how the fields of the MenuItem structure are 
  240. interpreted by PopChoose().  Their use is nearly identical to their use 
  241. under Intuition.
  242.  
  243. NextItem
  244.  
  245.   The next MenuItem in the list
  246.  
  247. LeftEdge, TopEdge
  248.   
  249.   These values hold the coordinates of the upper left hand corner of the
  250.   select box for the item, relative to the upper left hand corner of the
  251.   menu itself.  If the menu has a title, TopEdge will be silently
  252.   incremented by POPTITLEHEIGHT for rendering purposes to make room for the 
  253.   title.  This will be transparent to you (except when specifying the
  254.   Height field of the Menu structure, as noted above).
  255.  
  256. Width, Height
  257.  
  258.   These fields are the height and width of the select box for this item.
  259.  
  260. MutualExclude
  261.  
  262.   Items with the the CHECKIT flag set (see below) may form mutual exclusion
  263.   groups.  If this item is not CHECKED and is selected, all items designated
  264.   with the MutualExclude field will be un-CHECKED.  This field is a bitmask
  265.   where each bit refers to a single MenuItem in the list attached to the
  266.   Menu.  The first MenuItem corresponds to bit zero, the second to bit one,
  267.   and so on.  Setting a bit in this mask puts the corresponding MenuItem
  268.   into a mutual exclusion group with this item.  If you place an item in
  269.   its own mutual exclusion group, it will never be CHECKED.  In most cases
  270.   this is not what you want, but who knows?
  271.  
  272. ItemFill, SelectFill
  273.  
  274.   Exactly as described in the Intuition Reference Manual.
  275.  
  276. Command
  277.  
  278.   This field is ignored - there are no keyboard equivalents for pop-up menus.
  279.  
  280. SubItem
  281.  
  282.   In the current implementation, this field is ignored; menu sub-items are
  283.   unsupported.
  284.  
  285. NextSelect
  286.  
  287.   This field is unused -- extended selections are not supported.
  288.  
  289. Flags
  290.  
  291.   There are no pop-up-menu-specific flags for the MenuItem structure.  The
  292.   following are the flags defined in the Intuition Reference Manual along
  293.   with descriptions of how their use relates to pop-up menus.
  294.  
  295.   CHECKIT, CHECKED
  296.     These flags provide checkmarking functionality identical to that of 
  297.     Intuition's menus.  If the user tries to select a MenuItem that is
  298.     CHECKED, -1 will ALWAYS be returned; that is the nature of checkmarking.
  299.  
  300.   HIGHCOMP, HIGHBOX, HIGHIMAGE, HIGHNONE
  301.     Just as with Intuition, these specify the highlighting mode desired.  If
  302.     none of these are set, HIGHIMAGE is the default (because of the screwy
  303.     way Intuition defines the flag values); if no alternate imagery is
  304.     supplied in the SelectFill field, the effect will be the same as if
  305.     HIGHNONE was chosen.
  306.  
  307.   ITEMTEXT
  308.     This flag's function is identical to that explained in the Intuition 
  309.     Reference Manual.
  310.  
  311.   ITEMENABLED
  312.     As in Intuition, if this flag is not set, the item is "ghosted" and
  313.     unavailable for selection.  An attempt by the user to select an item
  314.     that is not ITEMENABLED will result in a return of -1.
  315.  
  316.   ISDRAWN, HIGHITEM, COMMSEQ
  317.     These flags are unused.
  318.  
  319. Appendix:  Problems
  320.  
  321. This code is not nearly perfect, although I confess my inability to provide 
  322. either clearly better solutions to the problems that make me fidget or 
  323. reasonably simple implementation schemes for the missing features.  This 
  324. Appendix details to some extent the concerns with which I send this code 
  325. into the Amiga community.
  326.  
  327. First, the inconsistencies in user interface.  Although it still seems to me
  328. that the consistent way to do these menus would have involved the delivery
  329. of IntuiMessages, the current scheme seems workable in nearly all scenarios
  330. I have imagined; in fact, PopChoose() seems simpler to use the way it is now.
  331. Suggestions or enhancements for the interface would be welcome.
  332.  
  333. Second, the POPREMEMBER business makes me a little nervous; altering the
  334. LeftEdge and TopEdge fields seems like a kludge.
  335.  
  336. Third, the way the optional menu title is handled seems too strange.  If
  337. the offsets of the MenuItems are going to be increased, it seems like
  338. the size of the window should be as well, in the interest of "transparency".
  339. But I couldn't bring myself to go around altering the window size....
  340.  
  341. Fourth, the code could probably be improved in a couple of ways:  there is
  342. altogether too much looping through MenuItem lists, and as always there may
  343. be bugs lurking in the code somewhere.  (clipping???)
  344.  
  345. Fifth, there are several crucial features missing, with no clue how they
  346. might be added: subitems, extended select.  In addition, the keyboard
  347. equivalents for Intuition menu items would be nice to support, but it is
  348. not at all clear to me how this would even be possible.
  349.  
  350. Sixth, bugs.  There are two that I know of.  1:  although the case where
  351. the POPTIDY flag is not set and the menu extends past the bottom and/or
  352. right edge of the screen is supported (the window is altered in size), the
  353. case where the screen's top and/or left border(s) is/are violated is not
  354. handled; the menu will not be placed if this happens, and -1 returned
  355. (at least under 1.2 this is what happens -- I am not sure if the
  356. OpenWindow() call behaves the same under 1.1). Speaking of which, I just 
  357. examined how the X window system (or at least the 'xterm' application) 
  358. handles pop-up menus that fly off the screen.  It appears to use the 
  359. equivalent of my POPTIDY flag, except when the menu would violate the bottom
  360. edge of the screen.  In this case, the menu is moved up as expected and THE 
  361. POINTER IS MOVED so that it is where it should be in relation to the menu.
  362. A little voice in my head gasped and said, "Never, Ever, move the user's
  363. pointer!!!", but is this wrong or what?  Should I add a POPMOVEPOINTER flag
  364. to work in conjunction with POPTIDY?
  365. 2:  it is possible for the user to do the mouse operation that would
  366. end the menu request before the window is rendered.  In this case, the
  367. event is not noticed and must be repeated.  This could be remedied if I
  368. could figure out how to query the state of the mouse buttons just after
  369. the window is opened.
  370.